/*
 * File:        playerList.h
 * Authors:     Jonathan Kotker (ee122-bw) and Shaan Mulchandani (ee122-bv)
 * Description: This header file defines the list of current players
 *              and utility methods to modify the list.
 */

#ifndef _PLAYERLIST_H
#define	_PLAYERLIST_H

#include "constants.h"
#include "playerListNode.h"
#include "playerStatistics.h"

#include <stdlib.h>
#include <time.h>

typedef struct {
    /* Head of the linked list of all players. */
    playerListNode* head;

} playerList;

/*
 * Returns the node associated with the player with the given
 * name, and NULL otherwise.
 */
playerListNode* accessPlayer(playerList* list, char* playerName) {
    if (list == NULL) return NULL;

    // Node corresponding to the player.
    playerListNode* playerNode = list->head;

    while (playerNode) {
        if ((strcmp(playerNode->statistics->name, playerName)) == 0) {
            return playerNode;
        }

        playerNode = playerNode->next;
    }

    return NULL;
};

/*
 * Returns the node associated with the given file descriptor,
 * and NULL otherwise.
 */
playerListNode* accessPlayerFd(playerList* list, int fd) {
    if (list == NULL) return NULL;

    // Node corresponding to the player.
    playerListNode* playerNode = list->head;

    while (playerNode) {
        if (playerNode->fileDescriptor == fd) {
            return playerNode;
        }

        playerNode = playerNode->next;
    }

    return NULL;
};

/*
 * Deallocates the dynamic memory allocated to this list.
 */
void clearList(playerList* list) {
    playerListNode* currNode;
    playerListNode* nextNode;
    currNode = list->head;

    while (currNode != NULL) {
        nextNode = currNode->next;
        free(currNode->statistics);
        free(currNode);
        currNode = nextNode;
    }
};

/* If the player with the given name does not already exist in the
 * list, adds a new player to the list, and associates the player connection
 * with the provided file descriptor. Otherwise, the player information
 * in the list is updated, and the file descriptor argument is ignored. */
void addPlayer(playerList* list,
        playerStatistics* playerStats, int fileDescriptor) {
    if (list == NULL) return;

    // Node corresponding to the player.
    playerListNode* playerNode;
    if ((playerNode = accessPlayer(list, playerStats->name)) == NULL) {
        playerListNode* newPlayer;
        playerStatistics* newStats;
        if (((newPlayer = malloc(sizeof (playerListNode))) == NULL) ||
                ((newStats = malloc(sizeof (playerStatistics))) == NULL)) {
            fprintf(stdout, "No free space available to allocate. \n");
            clearList(list);
            exit(EXIT_FAILURE);
        }

        updateStats(newStats, playerStats);
        strncpy(newStats->name, playerStats->name, EE122_MAX_NAME_LENGTH);
        newStats->name[EE122_MAX_NAME_LENGTH] = 0;

        newPlayer->fileDescriptor = fileDescriptor;
        newPlayer->statistics = newStats;
        newPlayer->next = list->head;
        newPlayer->prev = NULL;

        time(&(newPlayer->logInTime));

        if (newPlayer->next != NULL)
            newPlayer->next->prev = newPlayer;

        list->head = newPlayer;
    } else {
        updateStats(playerNode->statistics, playerStats);
    }
};

/* If the player with the given name exists in the list, removes
 * the player from the list. Otherwise, does nothing. */
void removePlayer(playerList* list, char* playerName) {
    if (list == NULL) return;

    // Node corresponding to the player.
    playerListNode* playerNode;

    if ((playerNode = accessPlayer(list, playerName)) != NULL) {
        if (list->head != playerNode)
            playerNode->prev->next = playerNode->next;
        else
            list->head = playerNode->next;

        playerNode->next = NULL;
        free(playerNode->statistics);
        free(playerNode);
    }
};

#endif	/* _PLAYERLIST_H */
